package com.tfswx.jcyw.dmzc.window;

import cn.hutool.core.codec.Base64;
import com.intellij.ui.JBColor;
import com.tfswx.jcyw.dmzc.component.TranslucenceJPanel;
import com.tfswx.jcyw.dmzc.enums.Lx;
import com.tfswx.jcyw.dmzc.util.ImageUtil;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;


public class ScreenCaptureWindow extends JFrame {

    private final JCheckBox rectRadioButton = new JCheckBox("矩形");
    private final JCheckBox circleRadioButton = new JCheckBox("画圆");
    private final JCheckBox lineRadioButton = new JCheckBox("画线");
    private final JCheckBox doodleRadioButton = new JCheckBox("涂鸦");
    private final JSlider cxSlider = new JSlider();
    private final JLabel cxSliderVal = new JLabel("3.0");
    private final JPanel colorPanel = new JPanel();
    private final JPanel btnPanel = new JPanel();
    private final JLabel pointLabel = new JLabel();
    private final JPanel outPanel = new JPanel();
    private final JPanel inPanel = new JPanel();
    private final JButton cancelButton = new JButton("取消");
    private final JButton okButton = new JButton("完成");
    private final JLabel imageLabel1;
    private final JLabel imageLabel2;
    private final Rectangle screenSize;
    private int mouseX = 0;
    private int mouseY = 0;
    private boolean isClip = true;
    private BufferedImage bi;

    public ScreenCaptureWindow() {
        super();
        setLayout(null);
        setAlwaysOnTop(true);

        byte[] screenImage = ImageUtil.getScreenImage();
        ImageIcon bgImage = new ImageIcon(screenImage);
        ImageIcon bgImage1 = new ImageIcon(screenImage);
        imageLabel1 = new JLabel(bgImage);
        imageLabel1.setBounds(0, 0, bgImage.getIconWidth(), bgImage.getIconHeight());
        imageLabel2 = new JLabel(bgImage1);
        imageLabel2.setBounds(0, 0, bgImage.getIconWidth(), bgImage.getIconHeight());

        screenSize = ImageUtil.getScreenSize();
        setBounds(screenSize);

        setUndecorated(true);
        setCursor(createCrosshairCursor());
//        setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));


        Container container = getContentPane();

        container.add(createBtnPanel());
        pointLabel.setLocation(0, screenSize.height - 50);
        pointLabel.setSize(300, 50);
        container.add(pointLabel);

        outPanel.setLayout(null);
        outPanel.setOpaque(false);
        outPanel.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));

        inPanel.setLayout(null);
        inPanel.setOpaque(false);
        inPanel.setSize(bgImage.getIconWidth(), bgImage.getIconHeight());
        inPanel.add(imageLabel2);

        outPanel.add(inPanel);
        container.add(outPanel);

        // 半透明遮罩
        TranslucenceJPanel translucenceJPanel = new TranslucenceJPanel(screenImage);
        translucenceJPanel.setBounds(0, 0, bgImage.getIconWidth(), bgImage.getIconHeight());
        translucenceJPanel.setTransparent(0.5f);
        translucenceJPanel.setBackground(Color.BLACK);
        container.add(translucenceJPanel);

        // 移动或者画线
        outPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                mouseX = e.getX();
                mouseY = e.getY();

                System.out.println("outPanel:" + mouseX + "," + mouseY);
            }
        });
        outPanel.addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                moveOrDraw(e.getXOnScreen() - screenSize.x, e.getYOnScreen() - screenSize.y);
            }
        });

        addWindowEvent();
        setVisible(true);
    }

    public static Cursor createCrosshairCursor() {
        ImageIcon imageIcon = ImageUtil.getImageIconByFileName("crosshair-cursor.png");
        Image cursor = imageIcon.getImage();
        return Toolkit.getDefaultToolkit().createCustomCursor(cursor, new Point(0, 0), "crosshairCursor");
    }

    private void moveOrDraw(int x, int y) {
        Point winPoint = getWinPoint(x, y);
        int xEnd = winPoint.x;
        int yEnd = winPoint.y;

        pointLabel.setText("当前坐标：" + xEnd + "，" + yEnd);

        System.out.println("moveOrDraw" + xEnd + "," + yEnd);

        Lx selected = getSelected();
        switch (selected) {
            case doodle:
                break;
            case rect:

                //鼠标移动时，在imageLabel展示的图像中，绘制点
                //1. 取得imageLabel中的图像
                ImageIcon img = (ImageIcon) imageLabel1.getIcon();

                //2. 创建一个缓冲图形对象 bi
                bi = new BufferedImage(img.getIconWidth(), img.getIconHeight(), BufferedImage.TYPE_INT_RGB);
                Graphics2D g2d = (Graphics2D) bi.getGraphics();

                //3. 将截图的原始图像画到 bi
                g2d.drawImage(img.getImage(), 0, 0, null);

                //4. 在鼠标所在的点，画一个点
                g2d.setColor(Color.RED); //设置画笔颜色为红色
                //因为如果鼠标向上，或向左移动时，xEnd > x, yEnd > y ，所以画圆的起点要取两者中的较小的，
                //而宽度和高度是不能  < 0 的，所以取绝对值
                g2d.drawRect(Math.min(mouseX, xEnd), Math.min(mouseY, yEnd), Math.abs(xEnd - mouseX), Math.abs(yEnd - mouseY));
                g2d.dispose();

                //5. 不需要保留在鼠标拖动过程中所画的线段，所以直接使用imageLabel.getGraphics()绘制
                //这样imageLabel.getIcon()并没有被改变，所以每次都只到原始截图和多了一条线，即为最后效果的演示
//                    Graphics g1 = imageLabel1.getGraphics();
//                    g1.drawImage(bi, 0, 0, null); //将处理后的图片，画到imageLabel
//                    g1.dispose();

                Graphics g2 = imageLabel2.getGraphics();
                g2.drawImage(bi, 0, 0, null); //将处理后的图片，画到imageLabel
                g2.dispose();
                break;
            case circle:
                break;
            case line:
                break;
            case move:

                outPanel.setLocation(xEnd - mouseX, yEnd - mouseY);
                inPanel.setLocation(-xEnd + mouseX, -yEnd + mouseY);

                setBtnPanel();
                break;
            case clip:
                inPanel.setLocation(-Math.min(mouseX, xEnd), -Math.min(mouseY, yEnd));
                outPanel.setBounds(Math.min(mouseX, xEnd), Math.min(mouseY, yEnd), Math.abs(xEnd - mouseX), Math.abs(yEnd - mouseY));
                break;
            default:
        }
    }

    private Point getWinPoint(int endX, int endY) {
        if (endX < 0) {
            endX = 0;
        } else if (outPanel.getWidth() + endX > screenSize.getWidth()) {
            endX = screenSize.width - outPanel.getWidth();
        }

        if (endY < 0) {
            endY = 0;
        } else if (outPanel.getHeight() + endY > screenSize.getHeight()) {
            endY = screenSize.height - outPanel.getHeight();
        }
        return new Point(endX, endY);
    }

    private void addWindowEvent() {

        this.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                String keyText = KeyEvent.getKeyText(e.getKeyCode());
                if ("Esc".equalsIgnoreCase(keyText)) {
                    undo();
                }
            }
        });

        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                mouseX = e.getXOnScreen();//记录鼠标按下时的坐标
                mouseY = e.getYOnScreen();

                System.out.println("this:" + mouseX + "," + mouseY);
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                Lx selected = getSelected();
                switch (selected) {
                    case clip:
                        System.out.println(outPanel.getWidth() + "x" + outPanel.getHeight());
                        if (outPanel.getWidth() > 0 && outPanel.getHeight() > 0) {
                            isClip = false;
                            setBtnPanel();
                        }
                        break;
                    case line:
                    case circle:
                    case rect:
                        //该方法只用作画线时处理
                        //鼠标弹起时需要将最后定为的图像 bi，调用imageLabel.setIcon()方法，设置进去。
                        //这样就可以将线段真的画进去了。为了使用变量 bi 将其转为 该类的private变量
                        imageLabel1.setIcon(new ImageIcon(bi));
                        imageLabel2.setIcon(new ImageIcon(bi));
                        break;
                    case doodle:
                    default:
                        setBtnPanel();
                }
            }

            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON3) {
                    undo();
                    return;
                }
                if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) {
                    if (outPanel.getWidth() <= 0 || outPanel.getHeight() <= 0) {
                        outPanel.setLocation(0, 0);
                        inPanel.setLocation(0, 0);
                        outPanel.setSize(getSize());
                    }

                    clipComplete();
                }
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseDragged(MouseEvent e) {
                moveOrDraw(e.getXOnScreen() - screenSize.x, e.getYOnScreen() - screenSize.y);
            }
        });
    }

    // region
    private JPanel createBtnPanel() {

//        btnPanel.setLayout(null);
        btnPanel.setVisible(false);

        btnPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));

        Dimension btnPanelBtnSize = new Dimension(70, 30);
        Dimension btnPanelSize = new Dimension(70 * 4 + 100 + 60 + 60, 30);

        rectRadioButton.addChangeListener(changeEvent -> {
            if (((JCheckBox) changeEvent.getSource()).isSelected()) {
                circleRadioButton.setSelected(false);
                lineRadioButton.setSelected(false);
                doodleRadioButton.setSelected(false);
            }
        });
        circleRadioButton.addChangeListener(changeEvent -> {
            if (((JCheckBox) changeEvent.getSource()).isSelected()) {
                rectRadioButton.setSelected(false);
                lineRadioButton.setSelected(false);
                doodleRadioButton.setSelected(false);
            }
        });
        lineRadioButton.addChangeListener(changeEvent -> {
            if (((JCheckBox) changeEvent.getSource()).isSelected()) {
                rectRadioButton.setSelected(false);
                circleRadioButton.setSelected(false);
                doodleRadioButton.setSelected(false);
            }
        });
        doodleRadioButton.addChangeListener(changeEvent -> {
            if (((JCheckBox) changeEvent.getSource()).isSelected()) {
                rectRadioButton.setSelected(false);
                circleRadioButton.setSelected(false);
                lineRadioButton.setSelected(false);
            }
        });

        cxSlider.setOpaque(true);
        cxSlider.setValue(30);
        cxSlider.setMaximum(100);
        cxSlider.setMinimum(10);
        cxSlider.setMajorTickSpacing(1);
        cxSlider.addChangeListener(changeEvent -> {
            JSlider source = (JSlider) changeEvent.getSource();
            cxSliderVal.setText(source.getValue() / 10F + "");
        });

        colorPanel.setOpaque(true);
        colorPanel.setBackground(JBColor.RED);
        colorPanel.setPreferredSize(new Dimension(30, 30));
        colorPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Color selectedColor = JColorChooser.showDialog(ScreenCaptureWindow.this, "选择颜色", colorPanel.getBackground());
                if (selectedColor != null) {
                    colorPanel.setBackground(selectedColor);
                }
            }
        });

        cxSliderVal.setOpaque(true);
        cxSliderVal.setPreferredSize(new Dimension(30, 30));

        btnPanel.add(rectRadioButton);
        btnPanel.add(circleRadioButton);
        btnPanel.add(lineRadioButton);
        btnPanel.add(doodleRadioButton);
        btnPanel.add(cxSlider);
        btnPanel.add(cxSliderVal);
        btnPanel.add(colorPanel);

//        btnPanel.setOpaque(false);
        btnPanel.setBackground(new Color(0, 0, 0, 26));
        btnPanel.setSize(btnPanelSize);

        cancelButton.setToolTipText("取消截图");
        cancelButton.setBounds(0, (30 - btnPanelBtnSize.height) / 2, btnPanelBtnSize.width, btnPanelBtnSize.height);
        btnPanel.add(cancelButton);

        okButton.setToolTipText("完成截图");
        okButton.setBounds(btnPanelBtnSize.width, (30 - btnPanelBtnSize.height) / 2, btnPanelBtnSize.width, btnPanelBtnSize.height);
        btnPanel.add(okButton);

        cancelButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                dispose();
            }
        });
        okButton.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                clipComplete();
            }
        });

        return btnPanel;
    }

    private Lx getSelected() {
        if (doodleRadioButton.isSelected()) {
            return Lx.doodle;
        } else if (lineRadioButton.isSelected()) {
            return Lx.line;
        } else if (circleRadioButton.isSelected()) {
            return Lx.circle;
        } else if (rectRadioButton.isSelected()) {
            return Lx.rect;
        } else if (isClip) {
            return Lx.clip;
        } else if (!isClip) {
            return Lx.move;
        }
        throw new RuntimeException("不支持的操作");
    }

    // region end

    private void resetAll() {
        doodleRadioButton.setSelected(false);
        lineRadioButton.setSelected(false);
        circleRadioButton.setSelected(false);
        rectRadioButton.setSelected(false);
    }

    private void undo() {
        if (outPanel.getWidth() > 0 && outPanel.getHeight() > 0) {
            outPanel.setSize(0, 0);
            inPanel.setLocation(0, 0);
            outPanel.setLocation(0, 0);
            resetAll();
            isClip = true;
            setBtnPanel();
        } else {
            dispose();
        }
    }

    private void clipComplete() {
        BufferedImage image = new BufferedImage(outPanel.getWidth(), outPanel.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = image.createGraphics();
        outPanel.paint(g2); // instead of just paint(g2);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            ImageIO.write(image, "jpg", bos);
            String base64 = Base64.encode(bos.toByteArray());
            System.out.println(base64);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private void setBtnPanel() {
        Lx selected = getSelected();
        if (selected != null) {
            int y = 10 + outPanel.getY() + outPanel.getHeight();
            if (y + btnPanel.getHeight() > getHeight()) {
                y = outPanel.getY() + outPanel.getHeight() - btnPanel.getHeight() - 10;
            }
            int x = outPanel.getX() + outPanel.getWidth() - btnPanel.getWidth() - 10;
            btnPanel.setLocation(x, y);
            btnPanel.setVisible(true);
        } else {
            btnPanel.setVisible(false);
        }
    }
}
